#Nota: el buffer pasado por parametro se libera
#Parámetros: dir buffer viejo, tama~no nuevo
#Retorna: dir buffer nuevo

#include <mips/regdef.h>
#include <sys/syscall.h>

.data
.align 2
msj_error: .asciiz "Error en realocar\n"

#define TAM_BYTE 			1
#define TAM_INT 			4
#define STDERR				3
# para el frame

#define TAM_FRAME 		48

#define POS_SRA_RA		40
#define POS_SRA_FP		36
#define POS_SRA_GP		32

# posicion para almacenar temporalmnt el valor del parámetro pasado
# tam del viejo buffer 
#define POS_LTA_TAM	28					
# dir del buffer viejo
#define POS_LTA_ARG0	24					
# tam del nuevo buffer
#define POS_LTA_ARG1  20			
# valor retornado
#define POS_LTA_RETORNO  16		

	.text
	.align 2
	.globl realocar
	.ent realocar

realocar:
	
# creación del frame
   .frame   $fp, TAM_FRAME, ra   
   .set noreorder
   .cpload t9
   .set reorder

   subu   	sp, sp, TAM_FRAME
   .cprestore POS_SRA_GP

	sw 			ra,  POS_SRA_RA(sp)
	sw 			$fp, POS_SRA_FP(sp)
#	sw 			gp,  POS_SRA_GP(sp)

	sw			a0, TAM_FRAME(sp)  				# argumento 0 = buffer
	sw			a1, TAM_FRAME+4(sp)				# argumento 1 = tam final

	sw			a0, POS_LTA_ARG0(sp)  		# guardar temporalmnt arg 0
	sw			a1, POS_LTA_ARG1(sp)  		# guardar temporalmnt arg 1

	move 		$fp, sp

# preparo los parámetros que se le pasaran a mymalloc

	lw			a0, POS_LTA_ARG1(sp)			# le paso al mymalloc el tam del nuevo buffer
			addu		a0, a0, 4									# primeros 4bytes tiene el tam del buffer
	jal 		mymalloc									# pido memoria

# si mymalloc retorna -1 hubo un error y saltamos para tratar el error
	beq v0, -1, retorno_error

# sino, guardo el valor de memoria que me devolvio en POS_LTA_RETORNO
	sw 			v0, POS_LTA_RETORNO(sp)
dire: 

	# t0		dirNew  	= direccion del nuevo buffer que se encuentra en v0 la dir devuelta por mymalloc	
	# t1 		dirOld		= direccion del viejo buffer
	# t2 		tamNewBuff= tam del nuevo buffer

	move 		t0, v0
	lw 			t1, POS_LTA_ARG0(sp) 
	lw			t2, POS_LTA_ARG1(sp)

	# en la primera posicion del buffer nuevo tengo q poner su tam
	sw			t2, 0(t0)
	addu		t0, t0, TAM_INT 					# le sumo a la dir del buf nuevo 4 porq el inicio est'a despues del tam del mismo
	sw			t0, POS_LTA_RETORNO(sp)		# actualizo en mem la nueva dir 

tam:
# Vemos si el puntero q recibio es nulo, en caso de serlo, devuelvo la dir y listo
	beqz 		t1, liberar								# si es nulo el puntero viejo, salto

# sino vamos a copiar el contenido del viejo buffer en el nuevo

	# t3		tamBufOld = Tam del viejo buffer
	# t4		valor 		= donde guardo el valor leido

	# el tam del buffer viejo se encuentra en la dir del buff -4
	subu		t5, t1, TAM_INT
	lw			t3, 0(t5)
 
# grabo en el nuevo buffer el contenido del anterior
loop:
	lb			t4, 0(t1)								# cargo en t4 el valor del buffer viejo[t3 -1] 
	sb      t4, 0(t0)								# guardo en buffer nuevo[t3 -1] el valor de t4
aka:
	# avanzo en TAM_BYTE la direccion de ambos buffers
	addu		t0, t0, TAM_BYTE
	addu		t1, t1, TAM_BYTE
	subu		t3, t3, TAM_BYTE				# resto en 1 el contador

	# si el contador (t3) == tam del nuevo buffer  
	beqz    t3, retorno_exito 			# si ya copie todo termino el loop
#	beq     t3, 5, retorno_exito  	# si ya copie todo termino el loop
	b loop

// ver q da de error

# cuando termino de copiar el contenido del buffer retorno el nuevo buffer
retorno_exito:

	# libero el buffer anterior
	lw 			a0, POS_LTA_ARG0(sp) 
	jal 		desalocar 
	b 			liberar

# si hay error devuelve 0 (mentira, ahora sale del prog)
retorno_error:
	li 		v0, SYS_write
	la 		a0,	STDERR
	la 		a1, msj_error
	li 		a2,	20
	syscall #escribo en stderr

	li 		v0,	SYS_exit #salgo del programa
	li 		a0, 1
	syscall

#	li 			v0, 0									# luego debe ir a liberar
#	b 		liberar
	
# se libera el stack frame
liberar:

# valor que voy a devolver: dir del buffer nuevo
	lw 			v0, POS_LTA_RETORNO(sp)

	move 		sp, $fp
	lw 			ra, POS_SRA_RA(sp)
	lw 			$fp, POS_SRA_FP(sp)
	addu 		sp, sp, TAM_FRAME
	j				ra

	.end realocar
